import datetime
import os
import pandas
from django.core.mail import EmailMultiAlternatives
from payroll.models import *
# 工资表拆分-转换HTML后调用发送模块进行发送
from salary.settings import BASE_DIR, DEFAULT_FROM_EMAIL, confirm_uri
import copy
from decimal import Decimal
# 企业微信推送工资条信息
from utils.wechat import PutWechatMessage


# 发送邮件模块
def SentMail(subject, contents, to_address):
    from_mail = DEFAULT_FROM_EMAIL
    msg = EmailMultiAlternatives(subject, contents, from_mail, [to_address])
    msg.content_subtype = 'html'
    if msg.send():
        return True
    else:
        return False


# 工资表约定
# 1，如果最后一行标题内容含有*号，则标记为不显示【邮件发送方式除外】
# 2，如果最后一列数据内容不是邮箱而是NO，则表明此数据为忽略数据，不发送不处理
# 3，如果最后一列的数据内容不是邮箱也不是NO，则表明只往钉钉或者企业微信发送【此时如果发送方式不含有钉钉或者企业微信，则报错不发送】

# 预处理函数
# 1，生成表头
# 2，统计合计有效条数【邮件有效，企业微信或者钉钉有效数】
# 3，根据发送方式，跳转对应的函数进行处理

def PreCondition(filename, title_row, name_colom, contact, how, paymonth, phone_colom, total_money_colom,
                 company_name, subject, send_way, url):
    import random, string
    # 随机字符串
    # mark_id = ''.join(random.sample(string.ascii_letters + string.digits, 10))
    # 发送时间戳
    mark_id = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
    # 定义初始数据
    preview = []  # 预览容器，预览格式为邮件的table格式
    total_count = 0  # 定义初始总数
    msg = ""  # 错误信息容器
    valid_count = 0  # 有效数据行数
    ignore_count = 0  # 忽略不处理的行数
    title = list()
    name_colom = int(name_colom)
    phone_colom = int(phone_colom)
    total_money_colom = int(total_money_colom)
    send_by_ent_wechat = False  # 发送方式初始值
    send_by_dingtalk = False    # 发送方式初始值
    send_by_email = False       # 发送方式初始值
    # 初始数据定义End
    # 打开excel工资表
    file = os.path.join(BASE_DIR, 'static', 'upload', 'payroll', filename)
    df = pandas.read_excel(file)
    # 获取数据表行数
    total_row = len(df)
    # 整合标题【邮件工资表和预览使用
    if title_row[0] == title_row[1]:
        # 单行标题
        # 获取标题行数据
        # pandas 第一行默认为标题行，相当于列头，列头不计数，所以，默认pandas的数据起始行数应该-2
        # 所以，工资表第一行必须为表格标题【合并单元格】如：2021年6月份工资表
        title_1 = df.loc[title_row[1] - 2].values
        title.append(title_1)
        # 如果是单行标题，表格行数-1则等于总行数
        total_count = total_row - 1
        # 循环起始行
        row = 1
    else:
        # 双行标题
        title_1 = df.loc[title_row[0] - 2].values
        title_2 = df.loc[title_row[1] - 2].values
        title.append(title_1)
        title.append(title_2)
        # 如果是单行标题，表格行数-2则等于总行数
        total_count = total_row - 2
        # 循环起始行
        row = 2
    # 判断发送方式【组合为：1，邮件；2，企业微信，3，钉钉，4，邮件+企业微信，5，邮件+钉钉】不存在钉钉+企业微信的情况
    send_way = str(send_way)
    if "email" in send_way:
        send_by_email = True
    if "dingtalk" in send_way:
        send_by_dingtalk = True
    if "ent_wechat" in send_way:
        send_by_ent_wechat = True

    # 循环，获取每一行的数据，整合标题+数据
    while row < int(total_row):
        row_values = df.loc[row].values
        username = df.iloc[row, name_colom - 1]   # 姓名
        phone = df.iloc[row, phone_colom - 1]     # 手机号
        email = df.iloc[row, -1]                  # 邮箱
        total_money = Decimal(df.iloc[row, total_money_colom - 1])  # 实发工资列
        if str(email).lower() == "no":
            # 此行忽略
            ignore_count = ignore_count + 1  # 忽略行数+1
            row = row + 1  # 跳过此行
        else:
            valid_count = valid_count + 1  # 有效行数+1
            # 未设置忽略的数据，开始处理
            # 整合标题行【邮件和前台预览】
            new_title = copy.deepcopy(title)  # 深拷贝一份，确保前面的数据不会重复发送
            sub_contents = new_title
            sub_contents.append(row_values)  # 插入数据
            # 转换为pandas的DataFrame
            # 然后转为html
            pd_dataframe = pandas.DataFrame(sub_contents)
            html = pd_dataframe.to_html(header=False, index=False)  # 去掉xy轴的123456789数字索引
            # 开始处理
            # 1，生成一个随机字符串，提供前端认证
            code = ''.join(random.sample(string.ascii_letters + string.digits, 45))
            # 1，邮件格式，修改样式
            # html样式替换，设置不换行，设置边框为灰色
            html = html.replace('border="1"',
                                'style="border:solid #ccc;'
                                'font-size:13px; '
                                'border-width:1px 0px 0px 1px;'
                                'border-collapse: collapse;'
                                'white-space: nowrap;"')
            html = html.replace("<td>",
                                "<td style='border:solid #ccc;"
                                " border-width:0px 1px 1px 0px; "
                                "padding:3px 5px 3px 5px;'>")
            html = html.replace("<tr>",
                                "<tr style='text-align: center;"
                                "vertical-align: middle;'>")
            html = html.replace('NaN', '')
            # 邮件工资条正文提示文本
            info1 = """
                    <br> *(保密邮件）<br>
                    <br>感谢您的辛勤工作，以上是您的工资条，请查收！
                    <br>1、公司实行薪酬保密制度，禁止员工在任何时候议论本人或他人工资信息。如有发现，将记过并通报全公司，扣除当月绩效20分/次，取消当年度各项奖金与评优，一年内不得晋升提级！
                    <br>2、工资内容确认无误请<a href='%s?code=%s' style="color: red; font-size:15px;">*点击这里进行确认*</a>，如有异议，请于收到工资条当天18时前联系：<a href='mailto:%s'>%s</a>，逾期未联系视为对工资条确认无误！
                    <br>3、此邮件由系统自动发出，请勿直接回复此邮件！              
                    """ % (confirm_uri, code, contact, contact)
            info2 = '''<br><br><br><b style="font-size:20px;">人力资源中心<br>%s</b>''' % company_name
            html_contents = html + info1 + info2

            # 将数据转为json，企业微信和钉钉使用
            json_contents = []
            # 如果是一行标题
            if title_row[0] == title_row[1]:
                title_json = title_1
            else:
                title_json = title_2

            # 1, 循环获取数据和标题
            start = 0
            while start < len(title_json):
                data_json = {}
                if "*" in title_json[start]:  # 如果含有星号，则忽略
                    start = start + 1
                else:
                    if title_json[start] == "nan":
                        start = start + 1
                    elif row_values[start] == "nan":
                        data_json['title'] = title_json[start]
                        data_json['contents'] = 0
                        json_contents.append(data_json)
                        start = start + 1
                    else:
                        data_json['title'] = title_json[start]
                        data_json['contents'] = row_values[start]
                        json_contents.append(data_json)
                        start = start + 1

            # 数据处理完毕，开始准备发送
            # 2,判断发送方式
            # 如果方式为1，则直接发送，方式为0，则先生成预览
            if how == 1:
                # tips: 不存在钉钉+企业微信模式
                # 直接发送，如果是邮件模式+企业微信模式
                if send_by_email:
                    # 1，邮件发送
                    status = SentMail(subject, html_contents, email)
                    # 添加发送记录到数据库
                    if status:
                        if SentContents.objects.filter(name=subject, username=username, userphone=phone, status=0):
                            # 已有记录，标记主题为重发然后保存
                            subject_save = subject + "【重发】【" + mark_id + "】"
                            sent_content = SentContents(name=subject_save, username=username, useremail=email, status=0,
                                                        mark_id=mark_id,
                                                        log='发送成功！', confirm=code, userphone=phone, total_money=total_money,
                                                        contents=json_contents, pay_month=paymonth, send_type=send_way)
                            sent_content.save()
                        else:
                            # 没有记录，直接保存
                            sent_content = SentContents(name=subject, username=username, useremail=email, status=0,
                                                        mark_id=mark_id,
                                                        log='发送成功！', confirm=code, userphone=phone, total_money=total_money,
                                                        contents=json_contents, pay_month=paymonth, send_type=send_way)
                            sent_content.save()
                    else:
                        if SentContents.objects.filter(name=subject, username=username, userphone=phone, status=1):
                            # 已有记录，标记主题为重发然后保存
                            subject_save = subject + "【重发】【" + mark_id + "】"
                            sent_content = SentContents(name=subject_save, username=username, useremail=email, status=1,
                                                        mark_id=mark_id,
                                                        log='数据校验通过，但邮件发送失败！', userphone=phone, total_money=total_money,
                                                        contents=json_contents, pay_month=paymonth, send_type=send_way)
                            sent_content.save()
                        else:
                            # 没有记录，直接保存
                            sent_content = SentContents(name=subject, username=username, useremail=email, status=0,
                                                        mark_id=mark_id,
                                                        log='发送成功！', confirm=code, userphone=phone,
                                                        total_money=total_money,
                                                        contents=json_contents, pay_month=paymonth, send_type=send_way)
                            sent_content.save()
                # 邮件加钉钉模式
                elif send_by_ent_wechat or send_by_dingtalk:
                    # 添加发送记录到数据库
                    # 保存数据即可，发送动作在循环完成所有的记录之后
                    if SentContents.objects.filter(name=subject, username=username, userphone=phone, status=0):
                        # 已有记录，标记主题为重发然后保存
                        subject_save = subject + "【重发】【" + mark_id + "】"
                        sent_content = SentContents(name=subject_save, username=username, useremail=email, status=0,
                                                    mark_id=mark_id,
                                                    log='发送成功！', confirm=code, userphone=phone, total_money=total_money,
                                                    contents=json_contents, pay_month=paymonth, send_type=send_way)
                        sent_content.save()
                    else:
                        # 没有记录，直接保存
                        sent_content = SentContents(name=subject, username=username, useremail=email, status=0,
                                                    mark_id=mark_id,
                                                    log='发送成功！', confirm=code, userphone=phone, total_money=total_money,
                                                    contents=json_contents, pay_month=paymonth, send_type=send_way)
                        sent_content.save()
                else:
                    # 没有选择任何发送方式
                    # 直接返回错误
                    msg = "您没有选择任何一种发送渠道，系统将取消所有操作！"
                    # 有错误
                    return {"errmsg": msg, "status": 0, "data": ""}
            else:
                # 预览模式
                preview.append(html)
            # 循环计数+1
            row = row + 1

    # 先检查后发送模式，返回预览数据
    if how == 0:
        return {"status": 2, "errmsg": "ok", "data": preview}

    # 加入mark_id
    url = url + "/" + str(mark_id) + "/wechat/"
    # 判断是否需要往企业微信发
    if send_by_ent_wechat:
        # 需要往企业微信发
        now_day = datetime.datetime.now().strftime("%Y年%m月%d日%H时%M分%S秒")
        description = "<div class=\"gray\">%s</div> <div class=\"normal\">%s</div><div " \
                      "class=\"highlight\">已发放！</div> " % (now_day, subject)

        wechat_subject = "工资条管家"
        ent_result = PutWechatMessage(wechat_subject, "textcard", description, url)
        # 判断微信消息是否推送成功
        if ent_result["errmsg"] == "ok":
            pass
        else:
            return {
                "status": 0,
                "errmsg": ent_result["errmsg"],
                "data": "",
                "mark_id": mark_id,
                }

    if send_by_dingtalk:
        # 需要往钉钉发送
        pass

    # 最后，保存统计数据
    new_index = SentIndex(name=subject, total=total_count, valid_total=valid_count, ignore_total=ignore_count,
                          mark_id=mark_id, )
    new_index.save()
    # 保存完毕
    # 删除上传的工资表
    # 发送完成，删除生成的文件
    if os.path.exists(file):
        os.remove(file)
    return {"status": 1,
            "errmsg": "ok",
            "data": "",
            "mark_id": mark_id,
            "ignore_count": ignore_count,
            "total_count": total_count,
            "valid_count": valid_count
            }
